#encoding:utf-8
'''
Created on 2015年7月5日

@author: LWD
desc:数据库操作类
@note:
1、执行带参数的ＳＱＬ时，请先用sql语句指定需要输入的条件列表，然后再用tuple/list进行条件批配
２、在格式ＳＱＬ中不需要使用引号指定数据类型，系统会根据输入参数自动识别
３、在输入的值中不需要使用转意函数，系统会自动处理
'''

import os
import MySQLdb
from MySQLdb.cursors import DictCursor
from DBUtils.PooledDB import PooledDB
import ConfigParser
 
"""
Config包含数据库的配置信息
"""
 
class PMysql(object):
    """
    @summary: MYSQL数据库对象，负责产生数据库连接 , 此类中的连接采用连接池实现
    @var: 获取连接对象:conn = Mysql.getConn()
    @var: 释放连接对象:conn.close()或del conn
    """
    #连接池对象
    __pool = None
    Option = {"host" : "", "password" : "", "username" : "", "database" : "", "port" : 3306, "charset":"utf8"}
    def __init__(self):
        """
        @summary: 数据库构造函数，从连接池中取出连接，并生成操作游标
        """
#        self._conn = MySQLdb.connect(host=Config.DBHOST , port=Config.DBPORT , user=Config.DBUSER , passwd=Config.DBPWD ,
#                              db=Config.DBNAME,use_unicode=False,charset=Config.DBCHAR,cursorclass=DictCursor)
        self._conn = PMysql.__getConn()
        self._cursor = self._conn.cursor()
    
    @staticmethod
    def read_options_config():
        '''
        @summary: 静态函数，通过读取配置文件设置数据库配置信息
        '''
        # print  os.path.dirname(os.path.abspath(__file__))
        cf = ConfigParser.ConfigParser()
        cf.read("./config.ini")
        
        PMysql.Option["host"] = cf.get("mysql", "host")
        PMysql.Option["password"] = cf.get("mysql", "password")
        PMysql.Option["username"] = cf.get("mysql", "username")
        PMysql.Option["database"] = cf.get("mysql", "database")
        # 端口有默认值，设置端口
        port = cf.get("mysql", "port")
        if not port.strip():
            PMysql.Option["port"] = port
 
    @staticmethod
    def setoptions(host, pwd, user, db, port = 3306):
        '''
        @summary: 静态函数，通过代码设置 数据库 配置信息
        '''
        PMysql.Option["host"] = host
        PMysql.Option["password"] = pwd
        PMysql.Option["username"] = user
        PMysql.Option["database"] = db
        PMysql.Option["port"] = port
        
    @staticmethod
    def __getConn():
        """
        @summary: 静态方法，从连接池中取出连接
        @return MySQLdb.connection
        """
        # 判断 配置信息是否已经设置
        if not (PMysql.Option["host"].strip() \
            and PMysql.Option["password"] \
            and PMysql.Option["username"] \
            and PMysql.Option["database"]):
            print "please set options first"
            raise ValueError('please call setoptions() or read_options_config() to set options first')
        
        if PMysql.__pool is None:
            __pool = PooledDB(creator=MySQLdb, mincached=1, maxcached=20,
                              host=PMysql.Option["host"], port=PMysql.Option["port"], 
                              user=PMysql.Option["username"], passwd=PMysql.Option["password"],
                              db=PMysql.Option["database"],use_unicode=False,
                              charset=PMysql.Option["charset"],cursorclass=DictCursor)
        return __pool.connection()
 
    def getAll(self,sql,param=None):
        """
        @summary: 执行查询，并取出所有结果集
        @param sql:查询ＳＱＬ，如果有查询条件，请只指定条件列表，并将条件值使用参数[param]传递进来
        @param param: 可选参数，条件列表值（元组/列表）
        @return: result list/boolean 查询到的结果集
        """
        if param is None:
            count = self._cursor.execute(sql)
        else:
            count = self._cursor.execute(sql,param)
        if count>0:
            result = self._cursor.fetchall()
        else:
            result = False
        return result
 
    def getOne(self,sql,param=None):
        """
        @summary: 执行查询，并取出第一条
        @param sql:查询SQL，如果有查询条件，请只指定条件列表，并将条件值使用参数[param]传递进来
        @param param: 可选参数，条件列表值（元组/列表）
        @return: result list/boolean 查询到的结果集
        """
        if param is None:
            count = self._cursor.execute(sql)
        else:
            count = self._cursor.execute(sql,param)
        if count>0:
            result = self._cursor.fetchone()
        else:
            result = False
        return result
 
    def getMany(self,sql,num,param=None):
        """
        @summary: 执行查询，并取出num条结果
        @param sql:查询SQL，如果有查询条件，请只指定条件列表，并将条件值使用参数[param]传递进来
        @param num:取得的结果条数
        @param param: 可选参数，条件列表值（元组/列表）
        @return: result list/boolean 查询到的结果集
        """
        if param is None:
            count = self._cursor.execute(sql)
        else:
            count = self._cursor.execute(sql,param)
        if count>0:
            result = self._cursor.fetchmany(num)
        else:
            result = False
        return result
 
    def insertOne(self,sql,value):
        """
        @summary: 向数据表插入一条记录
        @param sql:要插入的ＳＱＬ格式
        @param value:要插入的记录数据tuple/list
        @return: insertId 受影响的行数
        """
        self._cursor.execute(sql,value)
        return self.__getInsertId()
 
    def insertMany(self,sql,values):
        """
        @summary: 向数据表插入多条记录
        @param sql:要插入的ＳＱＬ格式
        @param values:要插入的记录数据tuple(tuple)/list[list]
        @return: count 受影响的行数
        """
        count = self._cursor.executemany(sql,values)
        return count
 
    def __getInsertId(self):
        """
        @summary: 获取当前连接最后一次插入操作生成的id,如果没有则为０
        """
        self._cursor.execute("SELECT @@IDENTITY AS id")
        result = self._cursor.fetchall()
        return result[0]['id']
 
    def __query(self,sql,param=None):
        if param is None:
            count = self._cursor.execute(sql)
        else:
            count = self._cursor.execute(sql,param)
        return count
 
    def update(self,sql,param=None):
        """
        @summary: 更新数据表记录
        @param sql: ＳＱＬ格式及条件，使用(%s,%s)
        @param param: 要更新的  值 tuple/list
        @return: count 受影响的行数
        """
        return self.__query(sql,param)
 
    def delete(self,sql,param=None):
        """
        @summary: 删除数据表记录
        @param sql: ＳＱＬ格式及条件，使用(%s,%s)
        @param param: 要删除的条件 值 tuple/list
        @return: count 受影响的行数
        """
        return self.__query(sql,param)
 
    def begin(self):
        """
        @summary: 开启事务
        """
        self._conn.autocommit(0)
 
    def end(self,option='commit'):
        """
        @summary: 结束事务
        """
        if option=='commit':
            self._conn.commit()
        else:
            self._conn.rollback()
 
    def dispose(self,isEnd=1):
        """
        @summary: 释放连接池资源
        """
        if isEnd==1:
            self.end('commit')
        else:
            self.end('rollback');
        self._cursor.close()
        self._conn.close()
        